/************************************************************************

								Heroes IV
					  Copyright 2000, The 3DO Company

	------------------------------------------------------------------
  						       artifact_properties.cpp

	$Header: /game/artifact_properties.cpp $

	$NoKeywords: $

 ************************************************************************/

// kill the 255+ character identifier warning.  Templates tend to exceed that easily.
#include "precompiled.h"
#pragma warning( disable: 4786 )

#include "artifact_properties.h"

#include <assert.h>
#include "artifact_keyword.h"
#include "artifact_slot.h"
#include "artifact_type.h"
#include "bitmap_group_cache.h"
#include "bitmap_pool.h"
#include "default_artifact_properties.h"
#include "elements_of.h"
#include "enum_operations.h"
#include "external_string.h"
#include "spell.h"
#include "table.h"
#include "table_ptr.h"

t_external_string const k_text_scroll( "scroll.artifact" );
t_external_string const k_text_parchment( "parchment.artifact" );

namespace
{
	enum t_artifact_file
	{
		k_artifact_file_none = -1,
		k_artifact_file_armor,
		k_artifact_file_item,
		k_artifact_file_special,
		k_artifact_file_weapon
	};

	char const* k_file_keywords[] =
	{
		"armor",
		"item",
		"special",
		"weapon"
	};

	struct t_artifact_properties
	{
		t_artifact_file		file_id;
		std::string			name;
		std::string         name_with_article;
		t_artifact_slot		slot;
		int					cost;
		t_artifact_level	level;
		std::string         help;
		std::string         pickup_text;
		std::string			history_text;
		bool				allowed_by_default;
		bool				cut;
	};

	enum
	{
		k_keyword_column,
		k_file_column,
		k_name_column,
		k_name_with_article_column,
		k_slot_column,
		k_cost_column,
		k_level_column,
		k_help_column,
		k_pickup_text_column,
		k_history_text_column,
		k_allowed_by_default_column
	};
}; // unnamed namespace

// -------------------------------------------------------------------------
// read a file id
// -------------------------------------------------------------------------
static t_artifact_file read_file_id( std::string string )
{
	t_artifact_file result;

	for (result = t_artifact_file(0); result < ELEMENTS_OF( k_file_keywords ); enum_incr(result))
	{
		if (stricmp( k_file_keywords[result], string.c_str() ) == 0)
			return result;
	}
	return k_artifact_file_none;
}

// -------------------------------------------------------------------------
// get properties for a given artifact image
// -------------------------------------------------------------------------
static t_artifact_properties const& get_properties( t_artifact_type artifact )
{
	assert( artifact >= 0 && artifact < k_artifact_type_count );

	static t_artifact_properties artifact_properties[k_artifact_type_count];
	static bool					 initialized = false;

	if (!initialized)
	{
		t_table_cache			skill_table( "artifacts" );
		t_table_ptr				table = skill_table.get();
		t_artifact_type         type;

		initialized = true;
		for (type = t_artifact_type(0); type < k_artifact_type_count; enum_incr(type))
		{
			t_artifact_properties& properties = artifact_properties[type];

			properties.file_id	= k_artifact_file_none;
			properties.level	= k_artifact_level_count;
			properties.cost		= 0;
			properties.slot		= k_artifact_slot_none;
			properties.cut		= false;
		}

		static t_artifact_type const k_cut_artifacts[] =
		{
			k_artifact_holy_crown,
			k_artifact_crown,
			k_artifact_ruby,
			k_artifact_sapphire,
			k_artifact_vampiric_amulet,
			k_artifact_chain,
			k_artifact_setting,
			k_artifact_left_onyx,
			k_artifact_right_onyx,
			k_artifact_dark_ruby,
			k_artifact_book_of_enchantment,
			k_artifact_chapter_one,
			k_artifact_chapter_two,
			k_artifact_chapter_three,
			k_artifact_chapter_four,
			k_artifact_binding,
			k_artifact_rod_of_chaos,
			k_artifact_rams_horn,
			k_artifact_crown_of_dragon_teeth,
			k_artifact_infant_dragon_wings,
			k_artifact_vial_of_sulfur,
			k_artifact_fire_snake,
			k_artifact_orb_of_summoning,
			k_artifact_sandalwood_key,
			k_artifact_ebony_key,
			k_artifact_ivory_key,
			k_artifact_mahogany_key,
			k_artifact_shield_of_resistance,
			k_artifact_blank_shield,
			k_artifact_left_elephant_tusk,
			k_artifact_right_elephant_tusk,
			k_artifact_rhino_horn,
			k_artifact_rising_sun,
			k_artifact_arms_of_legion,
			k_artifact_head_of_legion,
			k_artifact_legs_of_legion,
			k_artifact_statue_of_legion,
			k_artifact_torso_of_legion,
			k_artifact_victory_banner,
			k_artifact_boots_of_levitation,
		};

		int i;
		for ( i = 0; i < ELEMENTS_OF( k_cut_artifacts ); ++i )
			artifact_properties[ k_cut_artifacts[ i ] ].cut = true;

		std::string			keyword;
		t_table::iterator	line;

		// skip header
		line = table->begin();
		line++;
		line++;
		for (; line != table->end(); line++)
		{
			if (line->size() == 0)
				continue;

			keyword = (*line)[k_keyword_column];
			if (keyword.empty())
				continue;
			type = get_artifact_type( keyword );
			if (type == k_artifact_none)
				continue;

			t_artifact_properties& properties = artifact_properties[type];
			if ( properties.cut )
				continue;

			properties.file_id			 = read_file_id( (*line)[k_file_column] );
			properties.name				 = (*line)[k_name_column];
			properties.name_with_article = (*line)[k_name_with_article_column];
			properties.slot				 = get_artifact_slot( (*line)[k_slot_column] );
			properties.cost				 = atoi((*line)[k_cost_column].c_str() );
			properties.level			 = get_artifact_level( (*line)[k_level_column] );
			properties.help				 = (*line)[k_help_column];
			properties.pickup_text		 = (*line)[k_pickup_text_column];
			properties.history_text      = (*line)[k_history_text_column];
			
			std::string allowed_by_default = (*line)[k_allowed_by_default_column];
			
			int i;
			for ( i = 0; i < (int)allowed_by_default.size() && isspace(allowed_by_default[i]); i++ )
				;

			properties.allowed_by_default = (i < (int)allowed_by_default.size());
		}

#if !defined( NDEBUG )
		for (type = t_artifact_type(0); type < k_artifact_type_count; enum_incr(type))
			assert( artifact_properties[ type ].cut || artifact_properties[type].file_id != k_artifact_file_none );
#endif
	}
	return artifact_properties[artifact];
}

// -------------------------------------------------------------------------
// get properties for a given artifact image
// -------------------------------------------------------------------------
t_bitmap_layer_ptr get_icon( t_artifact_type artifact )
{
	assert( !is_cut( artifact ) );

	static bool					initialized = false;
	static t_bitmap_pool		k_artifact_icons;
	static int                  icon_ids[ k_artifact_type_count ];
	static t_bitmap_group_cache caches[] = 
	{
		"icons.artifacts.armor",
		"icons.artifacts.item",
		"icons.artifacts.special",
		"icons.artifacts.weapon"
	};

	if (!initialized)
	{
		std::vector<t_string_pair> layer_names( k_artifact_type_count );
		t_artifact_type            artifact;

		initialized = true;
		for (artifact = t_artifact_type(0); artifact < k_artifact_type_count; enum_incr(artifact))
		{
			t_string_pair & layer_name = layer_names[ artifact ];
			t_artifact_properties const & properties = get_properties( artifact );
			if ( !properties.cut )
			{
				layer_name.value = get_properties( artifact ).file_id;
				layer_name.keyword = get_keyword( artifact );
			}
			else
				layer_name.value = 0;
		}

		k_artifact_icons = t_bitmap_pool( caches, &(*layer_names.begin()), layer_names.size() );
	}
	return k_artifact_icons.get( artifact );
}

// -------------------------------------------------------------------------
// artifact slot for a given artifact image
// -------------------------------------------------------------------------
t_artifact_slot get_slot( t_artifact_type artifact )
{
	assert( !is_cut( artifact ) );
	return get_properties( artifact ).slot;
}

int get_cost( t_artifact_type artifact )
{
	assert( !is_cut( artifact ) );
	return get_properties( artifact ).cost;
}

t_artifact_level get_level( t_artifact_type artifact )
{
	assert( !is_cut( artifact ) );
	return get_properties( artifact ).level;
}

std::string get_name( t_artifact_type artifact, bool include_article )
{
	assert( !is_cut( artifact ) );
	if (include_article)
		return get_properties( artifact ).name_with_article;
	return get_properties( artifact ).name;
}

std::string get_artifact_type_name( t_artifact_type artifact_type )
{
	assert( !is_cut( artifact_type ) );
	if ( artifact_type == k_artifact_scroll )
		return k_text_scroll;
	if ( artifact_type == k_artifact_parchment )
		return k_text_parchment;
	return get_name( artifact_type );
}

std::string get_help_text( t_artifact_type artifact )
{
	assert( !is_cut( artifact ) );
	return get_properties( artifact ).help;
}

std::string get_pickup_text( t_artifact_type artifact )
{
	assert( !is_cut( artifact ) );
	return get_properties( artifact ).pickup_text;
}

std::string get_history_text( t_artifact_type artifact )
{
	assert( !is_cut( artifact ) );
	return get_properties( artifact ).history_text;
}

bool allowed_by_default( t_artifact_type artifact )
{
	assert( !is_cut( artifact ) );
	return get_properties( artifact ).allowed_by_default;
}

t_spell get_potion_effect( t_artifact_type artifact )
{
	assert( !is_cut( artifact ) );

	static t_spell effect[k_artifact_type_count];
	static bool    initialized = false;

	if (!initialized)
	{
		int const k_effects[][2] = 
		{
			{ k_artifact_vial_of_acid,		k_spell_effect_potion_of_acid },
			{ k_artifact_binding_liquid,	k_spell_effect_potion_of_binding },
			{ k_artifact_potion_of_cold,	k_spell_effect_potion_of_cold },
			{ k_artifact_cloud_of_despair,	k_spell_effect_potion_of_despair },
			{ k_artifact_potion_of_endurance,	k_spell_effect_potion_of_endurance },
			{ k_artifact_kreegan_fire,			k_spell_effect_potion_of_fire },
			{ k_artifact_potion_of_fire_resistance,	k_spell_effect_potion_of_fire_resistance },
			{ k_artifact_vial_of_choking_gas,		k_spell_effect_potion_of_gas },
			{ k_artifact_potion_of_healing,			k_spell_effect_potion_of_healing },
			{ k_artifact_potion_of_health,			k_spell_effect_potion_of_health },
			{ k_artifact_holy_water,				k_spell_effect_potion_of_holy_water },
			{ k_artifact_potion_of_luck,			k_spell_effect_potion_of_luck },
			{ k_artifact_potion_of_mana,			k_spell_effect_potion_of_mana },
			{ k_artifact_potion_of_mirth,			k_spell_effect_potion_of_mirth },
			{ k_artifact_vial_of_poison,			k_spell_effect_potion_of_poison },
			{ k_artifact_potion_of_quickness,		k_spell_effect_potion_of_quickness },
			{ k_artifact_potion_of_resistance,		k_spell_effect_potion_of_resistance },
			{ k_artifact_potion_of_restoration,		k_spell_effect_potion_of_restoration },
			{ k_artifact_vial_of_blinding_smoke,	k_spell_effect_potion_of_smoke },
			{ k_artifact_potion_of_speed,			k_spell_effect_potion_of_speed },
			{ k_artifact_potion_of_strength,		k_spell_effect_potion_of_strength }
		};
		int i;

		initialized = true;
		for (i = 0; i < k_artifact_type_count; i++)
			effect[i] = k_spell_effect_potion_of_acid;
		for (i = 0; i < ELEMENTS_OF( k_effects ); i++)
			effect[k_effects[i][0]] = t_spell(k_effects[i][1]);
	}
	return effect[artifact];
}

bool is_cut( t_artifact_type artifact )
{
	assert( artifact >= 0 && artifact < k_artifact_type_count );
	return get_properties( artifact ).cut;
}
